package hu.comicsans;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToggleButton;

/**
 * A játék dinamikusan mozgó objektumainak kezelése. Ezen kívül a pályát
 * inicializálja. Az egyes mozgó objektumok a játéktól tudják lekérdezni más
 * mozgó objektumok pozícióját. Indításkor minden mozgó objektumnak ad egy
 * induló pozíciót. Meghatározott időközönként behívja a hangyászsünt a pályára.
 */
public class Jatek implements Runnable {

	/**
	 * a pálya szélessége
	 */
	final static int szelesseg = 800;
	
	/**
	 * a pálya magassága
	 */
	final static int magassag = 600;
	
	/**
	 * a maximális raktárkészlet
	 */
	final static int maxRaktarKeszlet = 100;

	/**
	 * a pálya objektum
	 */
	public Palya palya;

	/**
	 * a hangyairtó spray
	 */
	public HangyaIrtoSpray hangyaIrtoSpray;
	
	/**
	 * a szagtalanító spray
	 */
	public SzagtalanitoSpray szagtalanitoSpray;

	/**
	 * ennek beállításával szakítható meg a thread
	 */
	public Boolean jatekVege = false;

	/**
	 * a threadet futtató objektum
	 */
	public static Jatek jatek;

	/**
	 * a pályát kirajzoló panel
	 */
	private static Ablak enAblakom;
	
	/**
	 * ki van-e választva a szagtalanító spray
	 */
	public Boolean szagtalanitoKivalasztva = false;
	
	/**
	 * ki van-e választva a hangyairtó spray
	 */
	public Boolean hangyaIrtoKivalasztva = false;

	/**
	 * hangyairtó spray számlálójának felirata
	 */
	private static JLabel hangyairtoLabel;
	
	/**
	 * szagtalanító spray számlálójának felirata
	 */
	private static JLabel szagtalanitoLabel;
	
	/**
	 * a játék végét jelző felirat
	 */
	private static JLabel jatekVegeLabel;
	
	/**
	 * szagtalanító spray gombja
	 */
	private static JToggleButton szagtalanitoBtn;
	
	/**
	 * hangyairtó spray gombja
	 */
	private static JToggleButton hangyairtoBtn;
	
	/**
	 * az egész ablakot kirajzoló JFrame
	 */
	private static JFrame frame;
	
	/**
	 * a játékot futtató thread
	 */
	private static Thread jatekThread;

	/**
	 * új játék létrehozása
	 * 
	 * @param ablak egy referencia a pálya paneljére
	 */
	public Jatek(Ablak ablak) {

		inicializalas(ablak);
	}

	/**
	 * Ez a metódus szimulálja a világot. Egységnyi időközönként frissíti a
	 * pálya minden dinamikusan mozgó objektumát, valamint meghívja az
	 * ütközéskezelő metódusokat.
	 * 
	 * @param elozoIdo Az előző hívás ideje.
	 * @param mostaniIdo A jelenlegi idő.
	 */
	void vilagSzimulalas(long elozoIdo, long mostaniIdo) {

		long dt = 20;
		
		// 20 millisecenként mozgatjuk az objektumokat, és detektáljuk az ütközést
		for (long ts = elozoIdo; ts < mostaniIdo; ts += dt) {
			long te = mostaniIdo < (ts + dt) ? mostaniIdo - elozoIdo : (ts + dt) - elozoIdo;

			palya.frissit(te);

			hangyaIrtoSpray.frissit(te);

			palya.utkozesekKezelese();
		}
	}

	/**
	 * A játék végét kezelő metódus.
	 * 
	 * @return igaz, ha vége a játéknak
	 */
	private boolean vege() {

		if (palya.mindenRaktarKiurult() || jatekVege) {
			return true;
		}

		return false;
	}

	/**
	 * Ezzel a metódussal fújhatjuk a sprayt egy megadott pozícióra.
	 * 
	 * @param posX A fújás X koordinátája.
	 * @param posY A fújás Y koordinátája.
	 */
	public void sprayFujas(double posX, double posY) {
		if (szagtalanitoKivalasztva) {
			palya.szagtalanitoFujas(posX, posY);
		} else if (hangyaIrtoKivalasztva) {
			palya.hangyaIrtoFujas(posX, posY);
		}

	}

	/**
	 * segédfüggvény annak eldöntésére, hogy két körnek van-e közös pontja
	 * 
	 * @param p1 az első kör középpontja
	 * @param r1 az első kör sugara
	 * @param p2 a második kör középpontja
	 * @param r2 a második kör sugara
	 * @return a két kör metszi-e egymást
	 */
	public static Boolean ketKorMetsziEgymast(Vektor p1, double r1, Vektor p2, double r2) {
		double tavolsag = Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));

		if (tavolsag > (r1 + r2)) {
			// Nincs metszes
			return false;
		}

		return true;
	}

	/**
	 * ez a függvény futtatja a játékot, külön szálon fut
	 */
	@Override
	public void run() {

		// eltároljuk az előző mért időt
		long elozoIdo = System.currentTimeMillis();

		while (!vege()) {
			//megmérjük a jelenlegi időt
			long mostaniIdo = System.currentTimeMillis();

			//leszimuláljuk a világot az előző időtől mostanáig
			vilagSzimulalas(elozoIdo, mostaniIdo);

			// a mostani idő lesz a következő körben az előző
			elozoIdo = mostaniIdo;
			
			//frissítjük a hangyairtó számlálóját
			hangyairtoLabel.setText("Hangyairto Spray: " + hangyaIrtoSpray.hatralevoFujasokSzama);
			
			if (hangyaIrtoSpray.kifogyott())
			{
				//letiltjuk a gombot
				hangyairtoBtn.setEnabled(false);
			}
			
			//frissítjük a szagtalanító számlálóját
			szagtalanitoLabel.setText("Szagtalanito Spray: " + szagtalanitoSpray.hatralevoFujasokSzama);
			
			if (szagtalanitoSpray.kifogyott())
			{
				//letiltjuk a gombot
				szagtalanitoBtn.setEnabled(false);
			}
			
			//újrarajzoltatjuk a pályát
			enAblakom.validate();
			enAblakom.repaint();

			//20 millisecet várunk
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		//vége a játéknak, letiltjuk a gombokat
		jatekVegeLabel.setText("A játék véget ért.");
		szagtalanitoBtn.setEnabled(false);
		hangyairtoBtn.setEnabled(false);
	}

	/**
	 * a játék inicializálása, új pálya és spray-k létrehozása
	 * 
	 * @param ablak egy referencia a pálya paneljére
	 */
	public void inicializalas(Ablak ablak) {
		palya = new Palya(this);
		hangyaIrtoSpray = new HangyaIrtoSpray(palya, 5);
		szagtalanitoSpray = new SzagtalanitoSpray(palya, 5);

		enAblakom = ablak;
	}
	
	/**
	 * ez a függvény hívódik meg legelőször
	 * 
	 * @param arg parancssori paraméterek
	 */
	public static void main(String arg[]) {

		// letrehozzuk a palya JPaneljet
		enAblakom = new Ablak();

		// letrehozunk egy uj jatekot, atadjuk az ablak referenciajat
		jatek = new Jatek(enAblakom);

		// adunk a palya panelnek referenciat a jatekra
		enAblakom.enJatekom = jatek;

		// ezzel a listenerrel figyeljuk az egerklikkelest
		PalyaMouseListener palyaML = new PalyaMouseListener(jatek);

		// hozzaadjuk az ablakhoz a listenert
		enAblakom.addMouseListener(palyaML);

		//a szagtalanító gomb action listenere
		SzagtalanitoActionListener szagAL = new SzagtalanitoActionListener(jatek);
		
		//a hangyairtó gomb action listenere
		HangyaIrtoActionListener irtoAL = new HangyaIrtoActionListener(jatek);

		// button group, hogy egyszerre csak az egyik lehessen benyomva
		ButtonGroup group = new ButtonGroup();

		szagtalanitoBtn = new JToggleButton("Szagtalanito Spray");
		szagtalanitoBtn.setPreferredSize(new Dimension(200, 30));
		szagtalanitoBtn.setMinimumSize(new Dimension(200, 30));
		szagtalanitoBtn.setMaximumSize(new Dimension(200, 30));
		szagtalanitoBtn.addActionListener(szagAL);

		hangyairtoBtn = new JToggleButton("Hangyairto Spray");
		hangyairtoBtn.setPreferredSize(new Dimension(200, 30));
		hangyairtoBtn.setMinimumSize(new Dimension(200, 30));
		hangyairtoBtn.setMaximumSize(new Dimension(200, 30));
		hangyairtoBtn.addActionListener(irtoAL);

		group.add(szagtalanitoBtn);
		group.add(hangyairtoBtn);

		hangyairtoLabel = new JLabel("Hangyairto Spray: " + jatek.hangyaIrtoSpray.hatralevoFujasokSzama);
		hangyairtoLabel.setPreferredSize(new Dimension(200, 30));
		hangyairtoLabel.setMinimumSize(new Dimension(200, 30));
		hangyairtoLabel.setMaximumSize(new Dimension(200, 30));

		szagtalanitoLabel = new JLabel("Szagtalanito Spray: " + jatek.szagtalanitoSpray.hatralevoFujasokSzama);
		szagtalanitoLabel.setPreferredSize(new Dimension(200, 30));
		szagtalanitoLabel.setMinimumSize(new Dimension(200, 30));
		szagtalanitoLabel.setMaximumSize(new Dimension(200, 30));

		jatekVegeLabel = new JLabel();
		jatekVegeLabel.setForeground(Color.red);
		jatekVegeLabel.setPreferredSize(new Dimension(200, 30));
		jatekVegeLabel.setMinimumSize(new Dimension(200, 30));
		jatekVegeLabel.setMaximumSize(new Dimension(200, 30));
		
		JButton ujJatekBtn = new JButton("Uj jatek inditasa");
		ujJatekBtn.setPreferredSize(new Dimension(200, 30));
		ujJatekBtn.setMinimumSize(new Dimension(200, 30));
		ujJatekBtn.setMaximumSize(new Dimension(200, 30));

		//az új játék gomb hatására reseteljük a játékot
		ujJatekBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				Jatek.resetJatek();
			}
		});

		ImageIcon image = new ImageIcon("jelmagy.png");
		JLabel jelmagyLabel = new JLabel(image);
		
		frame = new JFrame();

		frame.setTitle("HangyaKiller by Comic Sans");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLayout(new BorderLayout());
		frame.setResizable(false);
		
		//egy panel a gomboknak
		JPanel gombokPanel = new JPanel();
		gombokPanel.setMinimumSize(new Dimension(250, 200));
		gombokPanel.setMaximumSize(new Dimension(250, 200));
		gombokPanel.setPreferredSize(new Dimension(250, 200));
		gombokPanel.setLayout(new FlowLayout());

		gombokPanel.add(ujJatekBtn);
		gombokPanel.add(szagtalanitoBtn);
		gombokPanel.add(hangyairtoBtn);
		gombokPanel.add(hangyairtoLabel);
		gombokPanel.add(szagtalanitoLabel);
		gombokPanel.add(jatekVegeLabel);
		gombokPanel.add(jelmagyLabel);

		frame.add(enAblakom, BorderLayout.WEST);
		frame.add(gombokPanel, BorderLayout.EAST);

		frame.pack();
		frame.setVisible(true);

		//elindítjuk a játék threadet
		jatekThread = new Thread(jatek);
		jatekThread.start();
	}

	/**
	 * ennek segítségével resetelhetjük a játékot
	 */
	public static void resetJatek() {
		
		try {
			//szólunk a játéknak hogy vége van
			jatek.jatekVege = true;
			
			//megvárjuk míg kilép a szál
			jatekThread.join();
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		//kitöröljük a játék vége feliratot
		jatekVegeLabel.setText("");
		
		//visszakapcsoljuk a gombokat
		szagtalanitoBtn.setEnabled(true);
		hangyairtoBtn.setEnabled(true);
		
		jatek.jatekVege = false;
		
		//új játék objektum
		jatek.inicializalas(enAblakom);
		
		//új thread a játéknak
		jatekThread = new Thread(jatek);
		jatekThread.start();
	}
}